Skip to content

Parallelize CI lint jobs and switch to Debug variant#22637

Open
jkmassel wants to merge 15 commits intotrunkfrom
jkmassel/investigate-lint-speed
Open

Parallelize CI lint jobs and switch to Debug variant#22637
jkmassel wants to merge 15 commits intotrunkfrom
jkmassel/investigate-lint-speed

Conversation

@jkmassel
Copy link
Copy Markdown
Contributor

@jkmassel jkmassel commented Feb 27, 2026

Summary

  • Switch lint from Release to Debug variant (faster compilation, no R8)
  • Disable checkDependencies for app-level lint, avoiding redundant analysis of transitive dependencies
  • Move locale consistency checks into a separate parallel CI job
  • Split library lint (editor, image-editor) into separate parallel jobs
  • Regenerate lint baseline for Debug variant with MissingNullAnnotation checks excluded (Java-only, not relevant for Kotlin-first codebase – anything that has this warning is a prime candidate for replacement by Kotlin code)
  • Remove references to removed Vanilla build flavour and login module

CI timing comparison

Job Trunk PR Change
Lint WordPress 4m 14s 4m 32s +18s
Lint Jetpack 6m 10s 4m 29s -1m 41s
Lint libs:editor (inline) 3m 34s (new parallel job)
Lint libs:image-editor (inline) 3m 22s (new parallel job)
Locale Consistency (inline) 3m 1s (new parallel job)
Developer wait time 6m 10s 4m 32s -27%

Developer wait time is determined by the slowest job in the parallel group. The bottleneck shifts from Jetpack lint (6m 10s) to WordPress lint (4m 32s).

Trade-offs

  • checkDependencies false means lint won't detect issues in library module sources from app-level lint. Library modules are now linted in their own dedicated CI jobs instead.
  • Baseline was regenerated for the Debug variant. 357 entries from dependency analysis were removed (now covered by separate lib lint jobs). Net baseline size decreased from 731 to 390 non-MissingNullAnnotation issues.

Test plan

  • Lint WordPress job passes
  • Lint Jetpack job passes
  • Locale Consistency job passes
  • Lint libs:editor job passes
  • Lint libs:image-editor job passes
  • No new lint failures from variant/dependency changes
  • Timing validated across multiple CI runs

🤖 Generated with Claude Code

jkmassel and others added 3 commits February 27, 2026 12:04
Move locale consistency checks into a separate parallel CI job and
disable checkDependencies for app-level lint. This removes ~4-6 min
of gem install + fastlane overhead from each lint job's critical path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The baseline was generated with checkDependencies=true, so switching
it off causes 234 baseline entries to become "fixed" and surfaces new
UnusedResources errors. Reverting until the baseline can be regenerated.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Set checkDependencies=false for app-level lint to avoid scanning
  the entire dependency tree
- Add add_ignore_attr to local library string configs so merged
  strings are not flagged as unused without dependency checking
- Add separate CI lint jobs for editor, login, and image-editor
  libraries to maintain lint coverage

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wpmobilebot
Copy link
Copy Markdown
Contributor

wpmobilebot commented Feb 27, 2026

App Icon📲 You can test the changes from this Pull Request in Jetpack Android by scanning the QR code below to install the corresponding build.

App NameJetpack Android
Build TypeDebug
Versionpr22637-b4661f6
Build Number1488
Application IDcom.jetpack.android.prealpha
Commitb4661f6
Installation URL1vkn14rvcpq7o
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

@wpmobilebot
Copy link
Copy Markdown
Contributor

wpmobilebot commented Feb 27, 2026

App Icon📲 You can test the changes from this Pull Request in WordPress Android by scanning the QR code below to install the corresponding build.

App NameWordPress Android
Build TypeDebug
Versionpr22637-b4661f6
Build Number1488
Application IDorg.wordpress.android.prealpha
Commitb4661f6
Installation URL4k418ovncuj18
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

jkmassel and others added 6 commits February 27, 2026 13:07
The baseline was generated with checkDependencies=true, which meant
dependency-sourced issues were included. With checkDependencies=false,
the baseline needs to reflect app-module-only lint results.

This also captures MissingNullAnnotation warnings that were always
present but never baselined.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
With checkDependencies=false, lint can't see that certain resources
defined in the app are used by editor/login library modules. Add
targeted ignore rules in lint.xml for these specific resources
instead of regenerating the entire baseline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Debug variants skip R8/ProGuard minification during compilation,
which reduces lint wall time especially on cold caches. All app
code is identical between debug and release — BuildConfig.DEBUG
checks are runtime conditionals, not compile-time code removal.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve conflicts:
- lint.sh: Keep VanillaDebug variants (PR intent: faster lint)
- localization.rb: Keep add_ignore_attr (needed with checkDependencies
  disabled), drop removed Login Library module

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The login module was removed in PR #22564. Remove the now-invalid
libs:login lint CI step and login-specific lint ignore rules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jkmassel jkmassel marked this pull request as ready for review April 1, 2026 21:21
The Vanilla flavour no longer exists. Use lintWordpressDebug and
lintJetpackDebug instead of the non-existent VanillaDebug variants.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jkmassel jkmassel added this to the 26.8 milestone Apr 1, 2026
@jkmassel jkmassel self-assigned this Apr 1, 2026
jkmassel and others added 2 commits April 1, 2026 15:55
Switching to Debug caused 357 baseline mismatches (the baseline was
generated against Release). Regenerating the baseline would balloon it
from 8k to 65k lines. Keep Release variant — the speedup from this PR
comes from checkDependencies=false, parallel lib lints, and separating
locale checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lint Debug is faster than Release (no R8/minification). The blocker was
5,124 MissingNullAnnotation issues that only surface on Debug, ballooning
the baseline from 8k to 65k lines. Ignoring these checks entirely
(they were already partially suppressed for generated code) allows a
clean switch to Debug with a net baseline reduction (8k -> 4k lines).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dangermattic
Copy link
Copy Markdown
Collaborator

1 Warning
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.

Generated by 🚫 Danger

jkmassel and others added 3 commits April 1, 2026 17:07
Test code accounts for ~20% of source files but generates ~64% of
baseline issues (mostly DoNotMockDataClass). Skipping test source
analysis should meaningfully reduce lint wall time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jkmassel jkmassel changed the title Speed up CI lint jobs Parallelize CI lint jobs and switch to Debug variant Apr 1, 2026
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes CI lint/validation throughput by switching app lint to Debug, disabling dependency checking for lint, and parallelizing previously-serial checks into separate Buildkite steps.

Changes:

  • Switch WordPress/Jetpack lint tasks to Debug variants and disable lint.checkDependencies.
  • Split locale consistency and selected library lint into separate parallel Buildkite jobs.
  • Update lint configuration/baseline behavior to match the new Debug + no-dependency-analysis setup.

Reviewed changes

Copilot reviewed 4 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
fastlane/lanes/localization.rb Adjusts library string merge settings to match the new lint/dependency behavior.
config/lint/lint.xml Updates ignored lint issues and adds suppressions for resources now “invisible” with checkDependencies=false.
build.gradle Disables lint dependency checking at the app level.
.buildkite/pipeline.yml Adds parallel Locale Consistency + library lint steps alongside existing lint jobs.
.buildkite/commands/lint.sh Switches app lint commands (and SARIF path) from Release to Debug variants.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +64 to +67
if .buildkite/commands/should-skip-job.sh --job-type validation; then
exit 0
fi

Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Locale Consistency step uses should-skip-job.sh --job-type validation, which (per should-skip-job.sh) will skip when changes are limited to fastlane/**, config/**, and **/strings.xml. Since this job’s purpose is to validate Fastlane locale lists vs Gradle resourceConfigurations, skipping on those files can let inconsistencies slip through. Consider using a job-type/skip rule that still runs when fastlane/lanes/localization.rb (and related locale config) changes, or adjust the skip logic for this step accordingly.

Suggested change
if .buildkite/commands/should-skip-job.sh --job-type validation; then
exit 0
fi

Copilot uses AI. Check for mistakes.
Comment on lines +85 to +93
- label: "🕵️ Lint libs:editor"
command: |
if .buildkite/commands/should-skip-job.sh --job-type lint; then
exit 0
fi

.buildkite/commands/restore-cache.sh
./gradlew :libs:editor:lint
plugins: [$CI_TOOLKIT]
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This job runs ./gradlew :libs:editor:lint. If the intent is to lint the Debug variant for speed (matching the app lint switch to Debug), consider invoking the variant-specific task (e.g., :libs:editor:lintDebug) to avoid running additional variants. Also consider adding artifact_paths for lint reports (like the app lint steps) so failures are debuggable from CI artifacts.

Copilot uses AI. Check for mistakes.
Comment on lines +102 to +103
./gradlew :libs:image-editor:lint
plugins: [$CI_TOOLKIT]
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the editor lint step: ./gradlew :libs:image-editor:lint may run more than the Debug variant. If the goal is Debug-only lint for faster CI, prefer the variant-specific lint task (e.g., :libs:image-editor:lintDebug). Also add artifact_paths for lint reports so the job produces the same diagnostics as the app lint steps.

Suggested change
./gradlew :libs:image-editor:lint
plugins: [$CI_TOOLKIT]
./gradlew :libs:image-editor:lintDebug
plugins: [$CI_TOOLKIT]
artifact_paths:
- "**/build/reports/lint-results*.*"

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +53
<ignore path="**/res/color/aztec_format_button_selector_color.xml" />
<ignore path="**/res/color/primary_on_surface_disabled_selector.xml" />
<ignore path="**/res/values-night/colors_aztec.xml" />
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new UnusedResources ignores use very broad paths like **/res/color/..., which will suppress findings anywhere those filenames appear across the repo. To reduce the chance of hiding legitimate issues in other modules later, consider narrowing these ignores to the specific module path where these resources live (e.g., WordPress/src/main/res/...).

Suggested change
<ignore path="**/res/color/aztec_format_button_selector_color.xml" />
<ignore path="**/res/color/primary_on_surface_disabled_selector.xml" />
<ignore path="**/res/values-night/colors_aztec.xml" />
<ignore path="**/libs/editor/src/main/res/color/aztec_format_button_selector_color.xml" />
<ignore path="**/libs/editor/src/main/res/color/primary_on_surface_disabled_selector.xml" />
<ignore path="**/libs/editor/src/main/res/values-night/colors_aztec.xml" />

Copilot uses AI. Check for mistakes.
@ParaskP7
Copy link
Copy Markdown
Contributor

ParaskP7 commented Apr 2, 2026

👋 @jkmassel and team, I went through the changes and below my suggestions: (love the extra Lint speed btw ❤️ )


  1. Suggestion (💡): Consider using DOAndroid's approach to have Lint run on debug for PR builds, but on release for trunk builds. This way you wouldn't get blocked while releasing the apps on cases where Lint fails only for release builds. See DOAndroid's:

image image

FYI: From the above, you'll also notice that the DOAndroid team gets notified on Slack when such a Lint related trunk failure occurs.


  1. Suggestion (💡): Consider merging both the 🕵️ Lint libs:editor and 🕵️ Lint libs:image-editor into one job, and move that config within lint.sh itself. Then use it like wordpress and jetpack, command: .buildkite/commands/lint.sh library. The config can look something like:
if [ "$1" = "library" ]; then
  ./gradlew :libs:editor:lint :libs:image-editor:lint
  exit 0
fi

I am sure that doing the above wouldn't make this lint.sh library slower than any of the other lint.sh wordpress and lint.sh jetpack jobs, so you won't lose in speed, and actually save a Buildkite resource.

FYI: In addition, to fully replicate the previous checkDependencies true, I suggest adding all available Android libraries (modules) into that lint.sh library check, the rest of them are:

  • libs:analytics
  • libs:fluxc (?)
  • libs:mocks
  • libs:networking
  • libs:posttypes
if [ "$1" = "library" ]; then
  ./gradlew :libs:analytics:lint :libs:editor:lint :libs:fluxc:lint :libs:image-editor:lint :libs:mocks:lint :libs:networking:lint :libs:posttypes:lint :libs:image-editor:lint
  exit 0
fi

PS: Obviously, and as per Copilot's commends (here + here), use lintDebug instead of lint, or else lint"${BUILD_VARIANT^}", that is, if you also take the 1st suggestion above into consideration.


Let me know what you think! 💭

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants